import sys
sys.path.append('..')

import lexer_checker as lc

dfa_CONDITION_FUNCTION_INIT_CHARS = {
    'isalnum':'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
    'isalpha':'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
    'islower':'abcdefghijklmnopqrstuvwxyz',
    'isupper':'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
    'isdigit':'0123456789',
    'isxdigit':'0123456789abcdefABCDEF',
    'isgraph':'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~',
    'isspace':' \f\r\t\n\v',
    'isblank':' \t',
    'isprint':'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~ ',
    'ispunct':'!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'
}

dft_cond = {'cond':[], 'action':[], 'next':'Error'}
dfa_tk = {'b':['dfa', 'td', 0]}

test_cases = [
    # idx : 0
    ({},'"tokens" not exist! location: "{}"'),
    ({'tokens':{}}, 'there is not token item in "tokens"!'),
    ({'tokens':{'123':['char', '.', 0]}}, 'invalid token name: 123'),
    ({'tokens':{'aaa':['char', '', 0]}}, 'length error! expect:1, location:"tokens"."aaa".[1]'),
    ({'tokens':{'aaa':['char', '.', -999]}}, 'priority must larger than 0! location: "tokens"."aaa".[2]'),
    # idx : 5
    ({'tokens':{'aaa':['string', '.', 1]}}, 'length too short! location: "tokens"."aaa".[1]'),
    ({'tokens':{'aaa':['string', 'asdf', 1]}}, ''),
    ({'tokens':{'aaa':['dfa', 'asdf', 1]}}, '"asdf" is not exist! location: "tokens"."aaa".[1]'),
    ({'tokens':{'aaa':['asdf', 'asdf', 1]}}, 'unknow token type: "asdf", location: "tokens"."aaa".[0]'),
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, ''),
    # idx : 10
    ({'dfa':{'666':{'Start':[{'cond':['chars', '1'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'invalid dfa name: 666'),
    ({'dfa':{'td':{'One':[{'cond':['chars', '1'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'can not find "Start" state in "dfa"."td"'),
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1'], 'action':[], 'next':'End'}]}}, 'tokens':dfa_tk}, 'can not find default empty condition! location: "dfa"."td"."Start"'),
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1', '2'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'length error! expect:2, location:"dfa"."td"."Start".[0]."cond"'),
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1'], 'action':['asdf'], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'unknow action: "asdf", location: "dfa"."td"."Start"[0]'),
    # idx : 15
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1'], 'action':[], 'next':'EEE'}, dft_cond]}}, 'tokens':dfa_tk}, 'unknow state name: "EEE", location: "dfa"."td"."Start"[0]'),
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1'], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, '"action" not exist! location: "dfa"."td"."Start".[0]."action"'),
    ({'dfa':{'td':{'Start':[{'cond':['chars', '1'], 'action':[]}, dft_cond]}}, 'tokens':dfa_tk}, '"next" not exist! location: "dfa"."td"."Start".[0]."next"'),
    ({'dfa':{'td':{'Start':[{'cond':['range', 'as'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, \
        'type error! expect:<class \'list\'>, location: "dfa"."td"."Start".[0]."cond".[1]'),
    ({'dfa':{'td':{'Start':[{'cond':['range', ['a', 'b', 'c']], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'length error! expect:2, location: "dfa"."td"."Start".[0]."cond".[1]'),
    # idx : 20
    ({'dfa':{'td':{'Start':[{'cond':['range', ['a', 'b']], 'action':['read', 'push', 'continue'], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, ''),
    ({'dfa':{'td':{'Start':[{'cond':['range', ['aa', 'b']], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'length error! expect:1, location:"dfa"."td"."Start".[0]."cond".[1]"'),
    ({'dfa':{'td':{'Start':[{'cond':['function', 'noexist'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'unknow condition function: "noexist", location: "dfa"."td"."Start"[0]'),
    ({'dfa':{'td':{'Start':[{'cond':['function', 'isdigit'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, ''),
    ({'dfa':{'td':{'Start':[{'cond':['lllll', '2333'], 'action':[], 'next':'End'}, dft_cond]}}, 'tokens':dfa_tk}, 'unknow condition type: "lllll", location: "dfa"."td"."Start"[0]'),
    # idx : 25
    ({'blank_chars':[' ', '\\n', '\\t', '\\r', 'z', '$'], 'tokens':{'aaa':['string', 'asdf', 1]}}, ''),
    ({'blank_chars':['\\'], 'tokens':{'aaa':['string', 'asdf', 1]}}, 'illegal blank char: "\\", location: "blank_char".[0]'),
    ({'blank_chars':['\\aa'], 'tokens':{'aaa':['string', 'asdf', 1]}}, 'illegal blank char: "\\aa", location: "blank_char".[0]'),
    ({'dfa':{'td':{'Start':[dft_cond]}}, 'tokens':dfa_tk}, '"Start" state must has at least 2 condtions! location: "dfa"."td"."Start"'),
]

if __name__ == '__main__':

    checker = lc.LexerChecker(list(dfa_CONDITION_FUNCTION_INIT_CHARS.keys()))

    for idx in range(0, len(test_cases)):
        item = test_cases[idx]
        try:
            checker.check(item[0])
        except Exception as e:
            msg = str(e)
            if msg != item[1]:
                print('test failed! idx: %d'%(idx))
                print('expect: ' + item[1])
                print('output: ' + msg)
                exit(1)
